#pragma once 
#include<iostream>
#include<cstdlib>
#include<queue>
#include<pthread.h>
#include<assert.h>
#include<unistd.h>

using namespace std;
int gThreadNum=5;


template<class T>
class ThreadPool{
  public:
    ThreadPool(int threadnum=gThreadNum)
      :_isStart(false)
    {
      pthread_mutex_init(&_mutex,nullptr);
      pthread_cond_init(&_cond,nullptr);
      _threadNum=threadnum;

    }

    static void* Routine(void* args)
    {
      pthread_detach(pthread_self());
      ThreadPool<T>*p=(ThreadPool<T>*)args;
      while(1)
      {
        p->lockQueue();//锁住队列
        while(!p->haveTask())
        {
          p->waitForTask();// 等待任务，条件变量阻塞等待
        }
        T t=p->Pop();// have task 

        p->unlockQueue();
        //在自己的上下文处理任务
        cout<<"thread["<<pthread_self()<<"]: "<<t<<endl;

      }
    }
    void start()
    {
      assert(!_isStart);//保证线程池没被启动
      for(int i=0;i<_threadNum;i++)//创建线程
      {
        pthread_t temp;
        pthread_create(&temp,nullptr,Routine,this);
      }
      _isStart=true;
    }

    void Push(const T& in)//放任务
    {
      lockQueue();//加锁队列
      _taskQueue.push(in);//添加进队列
      choiceThreadForHandler();//选择一个线程去执行任务，条件变量唤醒线程
      unlockQueue();
    }

    ~ThreadPool()
    {
      pthread_cond_destroy(&_cond);
      pthread_mutex_destroy(&_mutex);
    } 
  private:
    void lockQueue(){pthread_mutex_lock(&_mutex);}
    void unlockQueue(){pthread_mutex_unlock(&_mutex);}
    bool haveTask(){return !_taskQueue.empty();}
    void waitForTask(){pthread_cond_wait(&_cond,&_mutex);}//无任务等待，把锁释放掉
    void choiceThreadForHandler(){pthread_cond_signal(&_cond);}//唤醒一个线程执行
    T Pop(){T temp= _taskQueue.front();_taskQueue.pop();return temp;}//拿任务
  private:
    bool _isStart;
    int _threadNum;
    queue<T> _taskQueue;//任务队列
    pthread_cond_t _cond;
    pthread_mutex_t _mutex;

};

